package com.wulian.gateway.configuration;

import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.wulian.common.config.FilterIgnorePropertiesConfig;
import com.wulian.common.constants.CommonConstants;

import lombok.extern.slf4j.Slf4j;

/**
 * @author 马志豪
 * @ClassName: TokenValidateFilter
 * @Description: TODO(用过网关过滤token是否有效, 如果被拦截器拦截将会返回处理的信息)
 * @date 2019年9月17日 下午3:10:07
 */
@Component
@Slf4j
public class TokenValidateFilter extends ZuulFilter {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;
    
    private static final List<String> activiti_editor_app_urls = Arrays.asList("activiti/static/editor-app","activiti/static/images","activiti/websocket");

    /**
     * 验证通过后,校验token准确性
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String url = request.getRequestURL().toString();
        //获取认证名称
        String token = request.getHeader(CommonConstants.USER_TOKEN);
        String userInfo = null;
        if (StringUtils.isNoneBlank(token)) {
            //用户请求时会在头部 header 传给我之前存储的token, 我用来验证
            //判断token是否存在
            if (redisTemplate.hasKey(CommonConstants.USER_TOKEN_PREFIEX + token)) {
                userInfo = redisTemplate.opsForValue().get(CommonConstants.USER_TOKEN_PREFIEX + token);
            }
        }
        //此处判断是否要拦截**************

        //*******************开始拦截****************************
        log.info(String.format("%s  拦截的url: %s", request.getMethod(), url));
        log.info("拦截的url: "+url+"拦截的token:"+token+"拦截的用户信息:"+userInfo);
        //没有加认证token 就没有访问权限
        if (StringUtils.isBlank(token)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("{\"resultFlag\":401,\"code\":401,\"body\":\"没有访问权限！\",\"msg\":\"没有访问权限！\"}");
            ctx.getResponse().setContentType("text/html;charset=UTF-8");
        } else if (userInfo == null) {
            //token失效了
            //用户提供的token检测出和redis不一样
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("{\"resultFlag\":401,\"code\":401,\"body\":\"token失效,请重新登录！\",\"msg\":\"token失效,请重新登录！\"}");
            ctx.getResponse().setContentType("text/html;charset=UTF-8");
        }
        return null;

    }

    /**
     * 过滤gateway配置中的url
     */
    @Override
    public boolean shouldFilter() {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String url = request.getRequestURL().toString();
        //过滤登录方法
        List<String> urls = filterIgnorePropertiesConfig.getUrls();
        if (null != urls && urls.size() > 0) {
            for (String s : urls) {
                if (url.contains(s)) {
                    return false;
                }
            }
        }
        
        //针对工作流的页面引用不需进行token验证
        if (null != activiti_editor_app_urls && activiti_editor_app_urls.size() > 0) {
            for (String s : activiti_editor_app_urls) {
                if (url.contains(s)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 设置过滤器执行顺序
     */
    @Override
    public int filterOrder() {
        return FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER - 3;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

}
